#include <stdint.h>

#include "driver_plf.h"
#include "driver_system.h"
#include "driver_pwm.h"

struct pwm_ctrl_t {
    uint32_t en:1;
    uint32_t reserved0:2;
    uint32_t out_en:1;
    uint32_t single:1;
    uint32_t reservaed1:27;
};

struct pwm_elt_t {
    uint32_t cur_cnt;
    uint32_t high_cnt;
    uint32_t total_cnt;
    struct pwm_ctrl_t ctrl;
};

struct pwm_regs_t {
    struct pwm_elt_t channel[PWM_CHANNEL_MAX];
};

extern struct pwm_regs_t *pwm_ctrl;

void pwm_set_duty(enum pwm_channel_t channel, uint32_t high_duty) {
	if(high_duty > 10000) { high_duty = 10000; }
	uint32_t total_count = pwm_ctrl->channel[channel].total_cnt;
	uint32_t high_count = total_count - (total_count * high_duty / 10000L); // !!! 注意：运算可能溢出 !!!
	pwm_ctrl->channel[channel].high_cnt = high_count;
}

uint32_t pwm_get_duty(enum pwm_channel_t channel) {
	uint32_t total_count = pwm_ctrl->channel[channel].total_cnt;
	uint32_t high_count = pwm_ctrl->channel[channel].high_cnt;
	return 10000 - (high_count * 10000L / total_count);
}

void pwm_update2(enum pwm_channel_t channel, uint32_t frequency, uint32_t high_duty) {
    if(high_duty > 10000) { high_duty = 10000; }
    GLOBAL_INT_DISABLE();
    uint32_t total_count = system_get_pclk() / frequency;
    uint32_t high_count = total_count - (total_count * high_duty / 10000L); // !!! 注意：运算可能溢出 !!!
    pwm_ctrl->channel[channel].total_cnt = total_count;
    pwm_ctrl->channel[channel].high_cnt = high_count;
    GLOBAL_INT_RESTORE();
}
